home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / faxstat / faxstat.c++ next >
C/C++ Source or Header  |  1994-08-01  |  8KB  |  308 lines

  1. /*    $Header: /usr/people/sam/fax/faxstat/RCS/faxstat.c++,v 1.29 1994/04/10 03:56:15 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25.  
  26. #include <stdlib.h>
  27. #include <ctype.h>
  28. #include <osfcn.h>
  29. #include <pwd.h>
  30. #include <termios.h>
  31. #include <unistd.h>
  32. #include <sys/ioctl.h>
  33.  
  34. #include "FaxStatClient.h"
  35. #include "SendStatus.h"
  36. #include "RecvStatus.h"
  37. #include "ServerStatus.h"
  38. #include "StrArray.h"
  39. #include "config.h"
  40.  
  41. #if defined(TIOCGWINSZ) && defined(CONFIG_WINSZHACK)
  42. #include <sys/stream.h>
  43. #include <sys/ptem.h>
  44. #endif
  45.  
  46. class faxStatApp {
  47. private:
  48.     fxStr        appName;    // for error messages
  49.     fxStrArray        senderNames;    // sender's full name (if available)
  50.     fxStrArray        jobs;        // jobs to ask status for
  51.     fxBool        allJobs;    // if true, ask for all send jobs
  52.     fxBool        recvJobs;    // if true, ask for received status
  53.     fxBool        debug;
  54.     fxBool        verbose;    // if true, enable protocol tracing
  55.     fxBool        multipleClients;// more than 1 client thread
  56.     int            ncols;        // number of columns for output
  57.     FaxStatClientArray    clients;    // client ``threads''
  58.     FaxSendStatusArray    sendStatus;    // collected send job status
  59.     FaxRecvStatusArray    recvStatus;    // collected recv status
  60.     FaxServerStatusArray serverStatus;    // collected server status
  61.  
  62.     FaxStatClient* newClient(const char* host);
  63.     void setupUserIdentity();
  64. public:
  65.     faxStatApp();
  66.     ~faxStatApp();
  67.  
  68.     void initialize(int argc, char** argv);
  69.     void open();
  70.  
  71.     void printServerStatus(FILE*);
  72.     fxBool hasServerStatus()        { return clients.length() > 0; }
  73.     void printSendStatus(FILE*);
  74.     fxBool hasSendStatus()        { return sendStatus.length() > 0; }
  75.     void printRecvStatus(FILE*);
  76.     fxBool hasRecvStatus()        { return recvStatus.length() > 0; }
  77.  
  78.     fxBool isRunning()
  79.     { return FaxStatClient::getClientsDone() < clients.length(); }
  80. };
  81.  
  82. faxStatApp::faxStatApp()
  83. {
  84.     allJobs = FALSE;
  85.     recvJobs = FALSE;
  86.     debug = FALSE;
  87.     verbose = FALSE;
  88.     ncols = -1;
  89. }
  90.  
  91. faxStatApp::~faxStatApp()
  92. {
  93.     for (int i = 0, n = clients.length(); i < n; i++) {
  94.     FaxStatClient* c = clients[i];
  95.     delete c;
  96.     }
  97. }
  98.  
  99. FaxStatClient*
  100. faxStatApp::newClient(const char* host)
  101. {
  102.     return new FaxStatClient(host, sendStatus, recvStatus, serverStatus);
  103. }
  104.  
  105. void
  106. faxStatApp::initialize(int argc, char** argv)
  107. {
  108.     extern int optind;
  109.     extern char* optarg;
  110.     int c;
  111.  
  112.     appName = argv[0];
  113.     u_int l = appName.length();
  114.     appName = appName.tokenR(l, '/');
  115.     fxBool noSendJobs = FALSE;
  116.     while ((c = getopt(argc, argv, "h:u:arswvD")) != -1)
  117.     switch (c) {
  118.     case 'a':            // display all send jobs
  119.         allJobs = TRUE;
  120.         break;
  121.     case 'D':            // debug
  122.         if (clients.length() > 0)
  123.         fxFatal("Debug incompatible with host specification.");
  124.         debug = TRUE;
  125.         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
  126.         break;
  127.     case 'h':            // server's host
  128.         if (debug)
  129.         fxFatal("Debug incompatible with host specification.");
  130.         clients.append(newClient(optarg));
  131.         break;
  132.     case 'r':            // display receive queue
  133.         recvJobs = TRUE;
  134.         break;
  135.     case 's':            // do not show jobs in send queue
  136.         noSendJobs = TRUE;
  137.         break;
  138.     case 'u':            // show send jobs for specific user
  139.         senderNames.append(optarg);
  140.         break;
  141.     case 'v':            // enable protocol tracing
  142.         verbose = TRUE;
  143.         break;
  144.     case 'w':            // widen output line
  145.         if (ncols == -1)
  146.         ncols = 132;
  147.         else if (ncols == 132)
  148.         ncols = 1000;        // something big
  149.         break;
  150.     case '?':
  151.         fxFatal("usage: %s"
  152.         " [-h server-host]"
  153.         " [-u user-name]"
  154.         " [-arsvw]"
  155.         " [jobs]",
  156.         (char*) appName);
  157.     }
  158.  
  159.     if (clients.length() == 0)
  160.     clients.append(newClient(""));
  161.     if (senderNames.length() == 0 && !noSendJobs)
  162.     setupUserIdentity();
  163.     if (optind < argc) {
  164.     // list of jobs to check on
  165.     jobs.resize(argc-optind);
  166.     for (u_int i = 0; optind < argc; i++, optind++)
  167.         jobs[i] = argv[optind];
  168.     }
  169.     multipleClients = (clients.length() > 1);
  170. #ifdef TIOCGWINSZ
  171.     winsize ws;
  172.     if (ncols == -1 && ioctl(fileno(stdout), TIOCGWINSZ, &ws) == 0)
  173.     ncols = ws.ws_col;
  174. #endif
  175.     if (ncols == -1)
  176.     ncols = 80;
  177. }
  178.  
  179. void
  180. faxStatApp::open()
  181. {
  182.     int i = 0;
  183.     while (i < clients.length()) {
  184.     FaxStatClient* c = clients[i];
  185.     c->setVerbose(verbose);
  186.     if (c->start(debug)) {
  187.         c->sendLine("serverStatus:\n");
  188.         if (jobs.length() > 0) {
  189.         for (int j = 0; j < jobs.length(); j++)
  190.             c->sendLine("jobStatus", jobs[j]);
  191.         } else if (allJobs) {
  192.         c->sendLine("allStatus:\n");
  193.         } else {
  194.         for (int j = 0; j < senderNames.length(); j++)
  195.             c->sendLine("userStatus", senderNames[j]);
  196.         }
  197.         if (recvJobs)
  198.         c->sendLine("recvStatus:\n");
  199.         c->sendLine(".\n");
  200.         i++;
  201.     } else {
  202.         clients.remove(i);
  203.     }
  204.     }
  205. }
  206.  
  207. void
  208. faxStatApp::setupUserIdentity()
  209. {
  210.     struct passwd* pwd = NULL;
  211.     char* name = cuserid(NULL);
  212.     if (!name) {
  213.     name = getlogin();
  214.     if (name)
  215.         pwd = getpwnam(name);
  216.     }
  217.     if (!pwd)
  218.     pwd = getpwuid(getuid());
  219.     if (!pwd)
  220.     fxFatal("Can not determine your user name.");
  221.  
  222.     fxStr namestr;
  223.     fxStr username = pwd->pw_name;
  224.     if (pwd->pw_gecos && pwd->pw_gecos[0] != '\0') {
  225.     namestr = pwd->pw_gecos;
  226.     u_int l = namestr.next(0, '&');
  227.     if (l < namestr.length()) {
  228.         /*
  229.          * Do the '&' substitution and raise the
  230.          * case of the first letter of the inserted
  231.          * string (the usual convention...)
  232.          */
  233.         namestr.remove(l);
  234.         namestr.insert(username, l);
  235.         if (islower(namestr[l]))
  236.         namestr[l] = toupper(namestr[l]);
  237.     }
  238.     namestr.resize(namestr.next(0,','));
  239.     } else
  240.     namestr = username;
  241.     if (namestr.length() == 0)
  242.     fxFatal("Bad (null) user name.");
  243.     senderNames.append(namestr);
  244. }
  245.  
  246. void
  247. faxStatApp::printServerStatus(FILE* fp)
  248. {
  249.     if (serverStatus.length() == 0) {
  250.     if (!multipleClients) {
  251.         const fxStr& modem = clients[0]->getModem();
  252.         if (modem == "")
  253.         fprintf(fp, "No servers active on \"%s\".\n",
  254.             (char*) clients[0]->getHost());
  255.         else
  256.         fprintf(fp, "No server active on \"%s:%s\".\n",
  257.             (char*) clients[0]->getHost(), (char*) modem);
  258.     } else
  259.         fprintf(fp, "No servers active on hosts.\n");
  260.     } else {
  261.     for (u_int i = 0; i < serverStatus.length(); i++)
  262.         serverStatus[i].print(fp);
  263.     }
  264. }
  265.  
  266. void
  267. faxStatApp::printSendStatus(FILE* fp)
  268. {
  269.     // sort and print send job status
  270.     sendStatus.qsort(0, sendStatus.length());
  271.     FaxSendStatus::printHeader(fp, ncols, multipleClients);
  272.     for (u_int i = 0; i < sendStatus.length(); i++)
  273.     sendStatus[i].print(fp, ncols, multipleClients);
  274. }
  275.  
  276. void
  277. faxStatApp::printRecvStatus(FILE* fp)
  278. {
  279.     // sort and print receive status
  280.     recvStatus.qsort(0, recvStatus.length());
  281.     FaxRecvStatus::printHeader(fp, multipleClients);
  282.     for (u_int i = 0; i < recvStatus.length(); i++)
  283.     recvStatus[i].print(fp, multipleClients);
  284. }
  285.  
  286. #include <Dispatch/dispatcher.h>
  287.  
  288. extern "C" int
  289. main(int argc, char** argv)
  290. {
  291.     faxStatApp app;
  292.     app.initialize(argc, argv);
  293.     app.open();
  294.     while (app.isRunning())
  295.     Dispatcher::instance().dispatch();
  296.     if (app.hasServerStatus())
  297.     app.printServerStatus(stdout);
  298.     if (app.hasSendStatus()) {
  299.     printf("\n");
  300.     app.printSendStatus(stdout);
  301.     }
  302.     if (app.hasRecvStatus()) {
  303.     printf("\n");
  304.     app.printRecvStatus(stdout);
  305.     }
  306.     return 0;
  307. }
  308.